<template>
	<view class="wyb-tabs-box" :style="boxStyleStr">
		<scroll-view
			class="wyb-tabs-scroll-view"
			:scroll-x="scroll"
			:scroll-left="scrollLeft"
			:enable-flex="true"
			:scroll-with-animation="scrollAnim"
			:style="{ height: height + 'rpx' }"
		>
			<view class="wyb-tabs-scroll-box" :style="{ height: height + 'rpx' }">
				<view class="wyb-tabs-label" id="tabsBox">
					<view
						:id="'tab' + index"
						class="wyb-tabs-label-item"
						v-for="(item, index) in tabs"
						v-text="item[cusLabel]"
						:key="index"
						@tap.stop="onTabsItemTap($event, index)"
						:style="[autoTabsItemStyle(index)]"
					/>
				</view>
				<view
					v-if="showSBlock"
					class="wyb-tabs-block"
					:style="{
						width: sBlockMode === 'fixed' ? sBlockWidth : everytabsWidth[currentUseForLeft] + Number(sBlockType.paddingHori) * 2 + 'px',
						height: autoSBlockHeight,
						left: scroll ? autoLeft : autoFixedLeft,
						bottom: sBlockType.type === 'line' ? '0' : '50%',
						borderRadius: sBlockType.type === 'rectangle' ? '5px' : '1000px',
						transitionDuration: 500 + 'ms',
						transform: 'translateX(-50%)' + (sBlockType.type === 'line' ? '' : ' translateY(53%)'),
						backgroundColor: autoBlockBgColor
					}"
				/>
			</view>
		</scroll-view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			currentUseForLeft: this.current.toString().slice(),
			scrollLeft: 0,
			scrollAnim: false,
			tabsWidthList: []
		};
	},
	computed: {
		autoTop() {
			let result = 44;
			// #ifndef H5
			result = 0;
			// #endif
			return result;
		},
		screenWidth() {
			return uni.getSystemInfoSync().screenWidth;
		},
		autoTabsItemStyle() {
			return function(index) {
				let padpx = uni.upx2px(Number(this.tabsPadding));
				return {
					paddingLeft: this.scroll ? (index === 0 ? `${padpx}px` : `${padpx / 2}px`) : 0,
					paddingRight: this.scroll ? (index === this.tabs.length - 1 ? `${padpx}px` : `${padpx / 2}px`) : 0,
					fontSize: `${uni.upx2px(Number(this.fontSize))}px`,
					width: this.scroll ? 'auto' : '100%',
					color: Number(this.currentUseForLeft) === index ? ('activeColor' in this.tabs[index] ? this.tabs[index]['activeColor'] : this.activeColor) : this.defaultColor,
					fontWeight: Number(this.currentUseForLeft) === index && this.activeWeight ? 'bold' : 'normal',
					transitionDuration: 500 + 'ms'
				};
			};
		},
		everytabsWidth() {
			let result = [];
			this.tabs.forEach(item => {
				result.push(item[this.cusLabel].length * uni.upx2px(Number(this.fontSize)));
			});
			return result;
		},
		autoLeft() {
			let pad = uni.upx2px(Number(this.tabsPadding));
			let result = 0;
			result += (this.everytabsWidth[this.currentUseForLeft] + pad * 2) / 2 + pad * this.currentUseForLeft;
			for (let i = 1; i <= this.currentUseForLeft; i++) {
				result += this.everytabsWidth[this.currentUseForLeft - i];
			}
			return `${result}px`;
		},
		autoFixedLeft() {
			let tabsBoxWidth = this.screenWidth;
			if (this.tabBoxStyle.width) {
				if (this.tabBoxStyle.width.toString().includes('px')) {
					tabsBoxWidth = uni.upx2px(parseFloat(this.tabBoxStyle.width));
				} else if (this.tabBoxStyle.width.toString().includes('px')) {
					tabsBoxWidth = parseFloat(this.tabBoxStyle.width);
				}
			}
			let tabsWidth = tabsBoxWidth / this.tabs.length;
			return `${(tabsWidth * (2 * Number(this.currentUseForLeft) + 1)) / 2}px`;
		},
		autoSBlockHeight() {
			let result = '';
			switch (this.sBlockType.type) {
				case 'line':
					result = `${this.sBlockType.height || 4}rpx`;
					break;
				case 'capsule':
				case 'rectangle':
					result = `${Number(uni.upx2px(this.fontSize)) + Number(this.sBlockType.paddingVert || 5) * 2}rpx`;
					break;
			}
			return result;
		},
		boxStyleStr() {
			let styleStr = '';
			let rootStyle = {
				width: this.screenWidth + 'px',
				height: this.height + 'rpx',
				top: this.autoTop + 'px',
				zIndex: this.zIndex,
				backgroundColor: this.bgColor
			};
			Object.keys(rootStyle).forEach(key => {
				styleStr += `${this.sortFieldMatch(key)}: ${rootStyle[key]}; `;
			});
			if (this.tabBoxStyle) {
				Object.keys(this.tabBoxStyle).forEach(key => {
					styleStr += `${this.sortFieldMatch(key)}: ${this.tabBoxStyle[key]}; `;
				});
			}
			return styleStr;
		},
		autoBlockBgColor() {
			let result = this.activeColor;
			try {
				if ('sBlockColor' in this.tabs[this.currentUseForLeft]) {
					result = this.tabs[this.currentUseForLeft]['sBlockColor'];
				} else if (this.sBlockColor) {
					result = this.sBlockColor;
				}
			} catch (e) {
				if (this.sBlockColor) {
					result = this.sBlockColor;
				} else {
					result = this.activeColor;
				}
			}
			return result;
		}
	},
	watch: {
		current(val) {
			this.currentUseForLeft = val.toString().slice();
		},
		scroll(val) {
			if (val) {
				this.$nextTick(() => {
					this.init();
				});
			}
		},
		tabBoxStyle() {
			this.$forceUpdate();
		}
	},
	props: {
		tabs: {
			type: Array,
			required: true,
			default() {
				return [];
			}
		},
		scroll: {
			type: Boolean,
			default: false
		},
		bgColor: {
			type: String,
			default: '#fff'
		},
		fontSize: {
			type: [String, Number],
			default: 30
		},
		height: {
			type: [String, Number],
			default: 80
		},
		current: {
			type: [String, Number],
			default: 0
		},
		tabsPadding: {
			type: [String, Number],
			default: 50
		},
		activeColor: {
			type: String,
			default: '#007aff'
		},
		defaultColor: {
			type: String,
			default: '#999'
		},
		activeWeight: {
			type: Boolean,
			default: true
		},
		cusLabel: {
			type: String,
			default: 'label'
		},
		showSBlock: {
			type: Boolean,
			default: true
		},
		sBlockMode: {
			type: String,
			default: 'auto',
			validator: function(value) {
				return ['fixed', 'auto'].indexOf(value) !== -1;
			}
		},
		sBlockWidth: {
			type: [String, Number],
			default: 20
		},
		sBlockColor: {
			type: String,
			default: ''
		},
		sBlockType: {
			type: Object,
			default() {
				return {
					type: 'line',
					height: 5,
					paddingHori: 5
				};
			}
		},
		tabBoxStyle: {
			type: Object,
			default() {
				return {};
			}
		},
		zIndex: {
			type: [String, Number],
			default: 2000
		}
	},
	mounted() {
		this.init();
	},
	methods: {
		async init() {
			if (this.scroll) {
				this.tabs.forEach(async (item, index) => {
					let tabsInfo = await this.getRect(`#tab${index}`);
					this.tabsWidthList.push(tabsInfo.width);
				});
				let tabBoxInfo = await this.getRect('.wyb-tabs-box');
				let eleWidth = tabBoxInfo.width;
				let currentTabsInfo = await this.getRect(`#tab${this.currentUseForLeft}`);
				let offsetLeft = currentTabsInfo.left;
				let scrollLeft = offsetLeft - (eleWidth - this.tabsWidthList[this.currentUseForLeft]) / 2;
				this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
				this.$nextTick(() => {
					this.scrollAnim = true;
				});
			}
		},
		async onTabsItemTap(e, index) {
			let tabBoxInfo = await this.getRect('.wyb-tabs-box');
			let eleWidth = tabBoxInfo.width;
			let offsetLeft = e.target.offsetLeft;
			let scrollLeft = offsetLeft - (eleWidth - this.tabsWidthList[index]) / 2;
			this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
			if (this.currentUseForLeft !== index) {
				this.$emit('change', {
					label: this.tabs[index][this.cusLabel],
					index
				});
			}
			this.currentUseForLeft = index;
		},
		getRect(selector) {
			return new Promise(resolve => {
				uni.createSelectorQuery()
					.in(this)
					['select'](selector)
					.boundingClientRect(rect => {
						if (rect) {
							resolve(rect);
						} else {
							resolve('no info');
						}
					})
					.exec();
			});
		},
		sortFieldMatch(field) {
			const stringArray = field.split('');
			let newField = field;
			stringArray.forEach(t => {
				if (/[A-Z]/.test(t)) {
					newField = field.replace(t, `-${t.toLowerCase()}`);
				}
			});
			return newField;
		}
	}
};
</script>

<style>
.wyb-tabs-box {
	position: static;
	width: 100%;
}

.wyb-tabs-scroll-view {
	width: 100%;
	display: flex;
	flex-direction: column;
	-webkit-overflow-scrolling: touch;
}

.wyb-tabs-scroll-view >>> ::-webkit-scrollbar {
	ddisplay: none;
	width: 0 !important;
	height: 0 !important;
	-webkit-appearance: none;
	background: transparent;
}

.wyb-tabs-scroll-box {
	width: 100%;
	position: relative;
}

.wyb-tabs-label {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: row;
	align-items: center;
}

.wyb-tabs-label-item {
	height: 100%;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	white-space: nowrap;
	transition-property: color;
	z-index: 20;
	border-bottom: 10rpx solid #efeff0;
}

.wyb-tabs-block {
	position: absolute;
	bottom: 0;
	transition-property: left, width, height, border, background-color;
	z-index: 100;
}
</style>
